package org.amn.concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;

import org.amn.config.AppConfig;
import org.amn.dto.IndexDTO;
import org.amn.file.FileManager;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * <p>
 * 描述:分发者,发起扫描Scanner.
 * </p>
 *
 * @see  org.amn.concurrent.Scanner
 * @author yangjun1120@gmail.com
 *
 */
public class Dispatcher implements Runnable {

    private static Logger logger = Logger.getLogger(Dispatcher.class);

    //    private Random r = new Random();

    private FileManager fm;

    private static ScheduledExecutorService ses;

    private List<Future<?>> futureList = new ArrayList<Future<?>>();

    private IindexQueue<IndexDTO> q;

    private int corePoolSize = 1;

    public Dispatcher(FileManager fileManager, int scannerCorePoolSize, IindexQueue<IndexDTO> queue) {
        this.fm = fileManager;
        this.q = queue;
        this.corePoolSize = scannerCorePoolSize;

        ses = Executors.newScheduledThreadPool(corePoolSize);

    }

    public ScheduledExecutorService getScheduledExecutorService() {
        return this.ses;
    }

    @Override
    public void run() {
        try {
            if (logger.isInfoEnabled()) {
                logger.info("Dispatcher heartbeat.");
            }

            doDispath();
        } catch (Throwable e) {
            logger.error("dispatcher exception", e);
        }

    }

    private void doDispath() {

        //scanner
        String[] penddingSubDir = fm.getPenddingSubDir();
        String[] enqueueSubDir = fm.getEnqueueSubDir();

        String[] totalDir = new String[penddingSubDir.length + enqueueSubDir.length];

        System.arraycopy(penddingSubDir, 0, totalDir, 0, penddingSubDir.length);
        System.arraycopy(enqueueSubDir, 0, totalDir, penddingSubDir.length, enqueueSubDir.length);

        penddingSubDir = null;
        enqueueSubDir = null;

        if (totalDir.length > 0) {

            int subCount = (totalDir.length / corePoolSize) == 0 ? 1 : (totalDir.length / corePoolSize);

            if ((totalDir.length % corePoolSize != 0) && (totalDir.length != 1)) {//目录总数为1时
                subCount += 1;
            }

            String[] subDirs = new String[subCount];

            int t = 0;
            for (int i = 0; i < totalDir.length; i++) {
                subDirs[t++] = totalDir[i];
                if (t == subCount) {
                    t = 0;
                    Scanner s = new Scanner(subDirs, fm, q);
                    Future<?> future = ses.submit(s);
                    futureList.add(future);
                    if (i < totalDir.length) {
                        subDirs = new String[((totalDir.length - i - 1) < subCount) ? (totalDir.length - i - 1)
                                : subCount];
                    }
                }
            }

            if (t != 0) {
                Scanner s = new Scanner(subDirs, fm, q);
                Future<?> future = ses.submit(s);
                futureList.add(future);
                t = 0;
            }

            subDirs = null;
        }

        //判断结束,block
        for (Future<?> f : futureList) {
            //boolean flag = false;

            try {
                f.get();
            } catch (Exception e) {
                logger.error("wait scanner end exception.", e);
            }

            //flag = f.isDone() || f.isCancelled();

        }

        futureList.clear();

    }

    public static void main(String[] args) throws Exception {

        //        ScheduledExecutorService dses = Executors.newScheduledThreadPool(2);//定时调度dispatcher

        ApplicationContext ctx = new ClassPathXmlApplicationContext("properties-config.xml");
        AppConfig appConfig = ctx.getBean(AppConfig.class);

        FileManager fm = new FileManager(appConfig);

        IndexBlockingQueue<IndexDTO> q = new IndexBlockingQueue<IndexDTO>(100);

        Dispatcher d = new Dispatcher(fm, 1, q);

        d.doDispath();

        ScheduledThreadPoolExecutor ss = (ScheduledThreadPoolExecutor) d.getScheduledExecutorService();

        Thread.sleep(2 * 1000);
        System.out.println(ss.getTaskCount());
        System.out.println(ss.getCompletedTaskCount());

        Thread.sleep(30 * 1000);

    }
}
